#include<iostream>
#include<string>
#include<unistd.h>
#include<cstdlib>
#include<vector>
#include<sys/types.h>
#include<functional>
#include<sys/wait.h>
#include"Task.hpp"
#include"Channel.hpp"
using namespace std;

using work_t = function<void()>;//定义一个函数work_t且返回类型是void

enum{ //枚举
    Ok=0,
    UsageError=1,
    PipeError,  //2
    ForkError   //3
};



void Usage(string proc)
{
     std::cout << "Usage: " << proc << " process-num" << std::endl;
}

class processpool
{
public:
    processpool(int n,work_t w)//构造函数
        :processnum(n)
        ,work(w)
    {

    }
    //channels:输出型参数
    //work_t work回调
    int InitProcessPool()//创建进程池
    {
        //创建多少个进程
        for(int i=0;i<processnum;i++)
        {
            //1.先创建管道
            int pipefd[2]={0};
            int n = pipe(pipefd);
            if(n<0)
            {
                return PipeError;
            }
            //2.创建指定个数的进程
            pid_t id = fork();
            if(id<0)
            {
                return ForkError;
            }
            //3.建立通信的信道
            if(id==0)
            {
                //子进程
                //关闭历史的wfd
                for(auto & c:channels)
                {
                    c.close();
                }
                close(pipefd[1]);//子进程负责读取
                dup2(pipefd[0],0);//重定向到直接从标准输出里进行读取
                work();//做自己的工作
                exit(0);
            }

            //父进程执行
            close(pipefd[0]);//父进程负责写入
            // Channel ch(pipefd[1],id);//对子进程进行管理;id是子进程
            // channels.push_back(ch);
            channels.emplace_back(pipefd[1],id);
        }
        return Ok;
    }

    void DispatchTask()//派发任务
    {
        int who = 0;
        int num  = 20;
        while(num--)
        {
            //1.选择一个任务，整数
            int task = tm.SelectTask(); 
            //2.选择一个子进程channel
            Channel& curr = channels[who++];
            who%=channels.size();
            //3.派发任务
            curr.send(task);
            sleep(2);
        }
    }

    void CleanProcessPool()//清理进程池
    {
        //版本1
        // for(auto &c:channels)
        // {
        //     c.close();
        // }

        // //4.回收进程
        // for(auto &c:channels)
        // {
        //     pid_t rid = waitpid(c.Id(),nullptr,0);
        //     if(rid>0)
        //     {
        //         cout<<"child: "<<rid<<"wait ... success"<<endl;
        //     }
        // }

        //版本2
        // for(int i = channels.size();i>=0;i--)//倒着退出
        // {
        //     channels[i].close();
        //     id_t rid = waitpid(channels[i].Id(),nullptr,0);
        //     if(rid>0)
        //     {
        //         cout<<"child: "<<rid<<"wait ... success"<<endl;
        //     }
        // }

        //版本3:在建立子进程的过程中关闭历史的wfd
        for(auto &c:channels)
        {
            c.close();
            pid_t rid = waitpid(c.Id(),nullptr,0);
            if(rid>0)
            {
                cout<<"child: "<<rid<<"wait ... success"<<endl;
            }
        }
 
    }
private:
    vector<Channel> channels;
    int &processnum;
    work_t work;
};